package service

import (
	"bytes"
	"encoding/json"
	"errors"
	"iot-bridge/iot_cmd_up/ping/conf"
	"iot-bridge/iot_cmd_up/ping/dao"
	"iot-bridge/iot_cmd_up/ping/ecode"
	"net/http"

	log "common/log4go.v1"
)

type PingUpServ struct {
}

type UpData struct {
	Cid       string `json:"cid"`
	UpTime    int64  `json:"up_time"`
	MessageId int    `json:"message_id"`

	ProductId  string `json:"product_id"`         //must  产品id  用于区分接入的硬件  能够使用一套核心数据 和  协议的 硬件,比如手表 watch  ,  ping  可以决定 上行时 数据扔向那个业务段
	Module     string `json:"module"`             //must  区分产品id 下不同的 业务模块  比如 闹钟 课堂  媒资  等
	ChangeTime int64  `json:"change_time,string"` //must  时间戳  单位 秒  数据变化时间,不断增大  ,设备端可能需要根据这个字段判断旧指令
	Version    string `json:"version"`            //maybe 版本号  可以在业务段的一个 模块下 对应唯一的  一份数据 ,操作类指令不需要
	Data       []byte `json:"data"`               //maybe 需要下发的协议数据， 存在时可以在核心数据校验时返回 ，数据不走虚拟设备的模块不需要传参， 比如复杂的通讯录模块
}

func NewPingUpServ() *PingUpServ {
	return &PingUpServ{}
}

func (this *PingUpServ) Push(upBody []byte) (needRestart bool, err error) {
	if upBody == nil {
		return
	}
	upData := &UpData{}
	err = json.Unmarshal(upBody, upData)
	if err != nil {
		log.Error("json.Unmarshal(m.Value, upData) data(%s) error(%v)", string(upBody), err)
		return
	}

	if len(upData.Cid) == 0 || len(upData.Module) == 0 {
		log.Error("cid(%s) Module(%d) exist empty param", upData.Cid, upData.Module)
		err = errors.New("param error")
		return
	}

	var buf = bytes.NewReader(upBody)
	req, err := http.NewRequest("POST", conf.Conf.PushUrl.Addr, buf)
	if err != nil {
		log.Error("http.NewRequest(%s) error(%v)", buf, err)
		needRestart = true
		return
	}
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

	body, err := dao.HttpDo(req)
	if err != nil {
		log.Error("dao.HttpDo(req) error(%v)", err)
		needRestart = true
		return
	}

	res := &PushRes{}
	err = json.Unmarshal(body, res)
	if err != nil {
		log.Error("json.Unmarshal(body, res) resData(%s) error(%v)", string(body), err)
		needRestart = true
		return
	}
	if res.Ret != ecode.OK {
		log.Error("push failed")
		err = errors.New("push error")
		needRestart = true
		return
	}
	return
}

type PushRes struct {
	Ret int32 `json:"ret"`
}
